﻿using System;
using Autofac;
using QQ2564874169.Core;

namespace QQ2564874169.TypeContainer.Autofac
{
    public class AutofacContainer : ITypeContainer
    {
        private ILifetimeScope _scope;

        public AutofacContainer(ILifetimeScope scope)
        {
            _scope = scope;
        }

        public void Dispose()
        {
            _scope.Dispose();
            _scope = null;
        }

        public ITypeContainer NewContainer(params ServiceParam[] param)
        {
            if (param == null || param.Length < 1)
                return new AutofacContainer(_scope.BeginLifetimeScope());

            return new AutofacContainer(_scope.BeginLifetimeScope(cb =>
            {
                foreach (var item in param)
                {
                    if (item.ServiceType == null)
                        throw new ArgumentException($"{nameof(ServiceParam.ServiceType)}不能是空。");

                    switch (item.Scope)
                    {
                        case ServiceScope.Dependency:
                        {
                            if (item.ImplementationType == null)
                                throw new ArgumentException("没有服务实现。");

                            var reg = cb.RegisterType(item.ImplementationType)
                                .As(item.ServiceType)
                                .InstancePerDependency();
                            if (item.IsExternallyOwned)
                                reg.ExternallyOwned();
                        }
                            break;

                        case ServiceScope.Container:
                        {
                            if (item.Instance != null)
                            {
                                var reg = cb.RegisterInstance(item.Instance)
                                    .As(item.ServiceType)
                                    .InstancePerLifetimeScope();
                                if (item.IsExternallyOwned)
                                    reg.ExternallyOwned();
                            }
                            else if (item.ImplementationType != null)
                            {
                                var reg = cb.RegisterType(item.ImplementationType)
                                    .As(item.ServiceType)
                                    .InstancePerLifetimeScope();
                                if (item.IsExternallyOwned)
                                    reg.ExternallyOwned();
                            }
                            else
                            {
                                throw new ArgumentException("没有服务实现。");
                            }
                        }
                            break;

                        case ServiceScope.Single:
                        {
                            if (item.Instance != null)
                            {
                                var reg = cb.RegisterInstance(item.Instance)
                                    .As(item.ServiceType)
                                    .SingleInstance();
                                if (item.IsExternallyOwned)
                                    reg.ExternallyOwned();
                            }
                            else if (item.ImplementationType != null)
                            {
                                var reg = cb.RegisterType(item.ImplementationType)
                                    .As(item.ServiceType)
                                    .SingleInstance();
                                if (item.IsExternallyOwned)
                                    reg.ExternallyOwned();
                            }
                            else
                            {
                                throw new ArgumentException("没有服务实现。");
                            }
                        }
                            break;

                        default:
                            throw new NotSupportedException(item.Scope.ToString());
                    }
                }

                SetBuilder(cb);
            }));
        }

        public object Resolve(Type serviceType)
        {
            return _scope.Resolve(serviceType);
        }

        protected virtual void SetBuilder(ContainerBuilder builder)
        {

        }
    }
}
